/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief Handler for routing packets between multiple hubs - implementation.
 * \author Antti Maula <antti.maula@tkk.fi>
 */

#include "routing.h"
#include "owndebug.h"
#include <assert.h>
#include <stdlib.h>

//*****************************************************************************
//*****************************************************************************
static TRouting routing;
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************

int routingInit(uint32_t default_gw)
{
  // Init IDMap, use 50 bins. Probably our networks will never contain
  // more than 50 AP nodes - and if they do - no problem; IDmap just
  // grows in length.
  idMapInit(&routing.routingmap, 50);

  // Set the default GW initially to 'default_gw'
  routingSetDefaultGW(default_gw);

  return ROUTING_OK;
}
//*****************************************************************************

void routingDeinit(void)
{
  // Iterate and free
  TIDMapEntryIterator iter;
  const TIDMapEntry *entry;
  idMapGetNextEntryIterator(&routing.routingmap, &iter);
  while((entry = idMapGetNextEntry(&routing.routingmap, &iter))) {
    free((void*)entry->entry);
  }

  // Deinit idMap
  idMapDeinit(&routing.routingmap);

  // Do Nada
  dPrint(3,"Routing Module Deinitialized.");
  return;
}
//*****************************************************************************
//*****************************************************************************

void routingSetDefaultGW(uint32_t default_gw)
{
  // Store defaultgw.
  routing.default_gw = default_gw;
}
//*****************************************************************************

uint32_t routingGetRoute(uint32_t nodeID)
{
  const TIDMapEntry *entry = idMapGetEntry(&routing.routingmap, nodeID);
  if (entry) {
    const TRoutingEntry *rentry = entry->entry;
    return rentry->gateway_id;

  } else {
    // Entry not found, hence return default gw.
    return routing.default_gw;

  }
}
//*****************************************************************************

int routingSetRoute(uint32_t nodeID,
                    uint32_t gatewayID)
{
  // Try setting a route.
  int result = -1;
  
  // Try to find existing entry first.
  const TIDMapEntry *existing = idMapGetEntry(&routing.routingmap, nodeID);

  if (existing) {
    // Existing entry found: modify gateway entry only.
    TRoutingEntry *rentry = existing->entry;

    dPrint(ODVINFO,"Route for 0x%08x already exists. Replacing gateway 0x%08x with 0x%08x",
           nodeID, rentry->gateway_id, gatewayID);
    
    rentry->gateway_id = gatewayID;
    rentry->distance = 16;
    result = 0;
    
  } else {
    // Add entry to IDMap.
    TRoutingEntry *rentry = malloc(sizeof(TRoutingEntry));
    assert(rentry != NULL);
    
    rentry->target_id = nodeID;
    rentry->gateway_id = gatewayID;
    rentry->distance = 16;
    
    result = idMapAddEntry(&routing.routingmap, nodeID, rentry);

  }

  if (result) {
    dPrint(ODERROR,
           "Failed to add routing entry 0x%08x -> 0x%08x, entry already exists!",
           nodeID, gatewayID);
  }

  return result;
}
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
